﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GanagroLiteData;
using Csla.Validation;
using GeneralUtilities;

namespace GanagroLiteBO
{
    public partial class PESAJES_BO : IOperacion
    {
        private PESAJE currentPesajeDO;

        #region Public Properties
        private short _ultimaGanancia;
        private bool _alreadyExists = false;

        public short UltimaGanancia
        {
            get { return _ultimaGanancia; }
        }

        private short _gananciaVida;

        public short GananciaVida
        {
            get { return _gananciaVida; }
        }

        private short _diasUltPesaje;

        public short DiasUltPesaje
        {
            get { return _diasUltPesaje; }
            set { _diasUltPesaje = value; }
        }

        private short _diasVida;

        public short Diasvida
        {
            get { return _diasVida; }
            set { _diasVida = value; }
        }

        private DateTime _fechaUltimoPesaje;

        public DateTime FechaPesajePrevio
        {
            get { return _fechaUltimoPesaje; }
            set { _fechaUltimoPesaje = value; }
        }

        private DateTime _fechaPrimerPesaje;

        public DateTime FechaPrimerPesaje
        {
            get { return _fechaPrimerPesaje; }
            set { _fechaPrimerPesaje = value; }
        }
        
        public short? Peso
        {
            get { return _Peso; }
            set
            { 
                if (_Peso != value)
                {
                    _Peso = value;
                    VALOR1 = value;
                    FirePropertyChangedNotification("Peso");
                    if (_alreadyExists == false)
                    {
                        CalcularPromediosNuevos(value);
                    }
                    else
                    {
                        CalcularGananciaPromedioCorriente(value);
                    }

                }
            }
        }


        private void CalcularPromediosNuevos(short? value)
        {
                if (!string.IsNullOrEmpty(this._CODIGO))
                {
                    GLiteBO gbo = new GLiteBO(CODIGO);

                    if (gbo.TienePesajes())
                    {
                        List<string> UltPesoYFecha = gbo.GetUltimoPesoYFecha();
                        List<string> PrimerPesoYFecha = gbo.GetPrimerPesoYFecha();

                        short UltimaGananciaPeso = (short)(value -  short.Parse(UltPesoYFecha[0]));
                        _fechaUltimoPesaje = DateTime.Parse(UltPesoYFecha[1]);
                        if (_fechaUltimoPesaje < this.FECHA)
                        {
                            _diasUltPesaje = (short)((TimeSpan)(this.FECHA - _fechaUltimoPesaje)).Days;
                            _ultimaGanancia = (short)(UltimaGananciaPeso * 1000 / _diasUltPesaje);  // 

                            short GananciaVidaPeso = (short)(value - short.Parse(PrimerPesoYFecha[0]));
                            _fechaPrimerPesaje =  DateTime.Parse(PrimerPesoYFecha[1]);

                            _diasVida = (short)((TimeSpan)(this.FECHA - _fechaPrimerPesaje)).Days;
                            _gananciaVida = (short)(GananciaVidaPeso * 1000 / _diasVida);
                        }

                    }
                }
        }


        private void CalcularGananciaPromedioCorriente(short? value)
        {
            if (!string.IsNullOrEmpty(this._CODIGO))
            {
                GLiteBO gbo = new GLiteBO(CODIGO);

                if (gbo.TienePesajes())
                {
                    List<string> PesajePrevioYFecha = gbo.PesajePrevioYFecha(this.FECHA);
                    short UltimaGananciaPeso = (short)(value -short.Parse(PesajePrevioYFecha[0]));
                    _fechaUltimoPesaje = DateTime.Parse(PesajePrevioYFecha[1]);
                    if (_fechaUltimoPesaje < this.FECHA)
                    {
                        _diasUltPesaje = (short)((TimeSpan)(this.FECHA - _fechaUltimoPesaje)).Days;
                        _ultimaGanancia = (short)(UltimaGananciaPeso * 1000 / _diasUltPesaje);  // 
                    }

                }
            }

        }

        public TiposGananciaDiaria CalidadGananciaVida
        {
            get {
                return getTipoGanancia(_gananciaVida);
                }
        }

        public TiposGananciaDiaria CalidadUltimaGanancia
        {
            get
            {
                return getTipoGanancia(_ultimaGanancia);
            }
        }
        
        #endregion

        #region constructors
        public PESAJES_BO(List<string> contenedor,NotaBO nota,short lote)
        {
            this.Contenedor = contenedor;
            this.FECHA = nota.Fecha;
            this.Nota = nota.Nota;
            this.OPERACION = (short)nota.TipoOperacion;
            this.lote = lote;
            AddAdtlBusinessRules();
            this.Peso = 0;

        }

        public PESAJES_BO(List<string> contenedor, NotaBO nota, Int32 precioKilo)
        {
            this.Contenedor = contenedor;
            this.FECHA = nota.Fecha;
            this.Nota = nota.Nota;
            this.OPERACION = (short)nota.TipoOperacion;
            this.VALOR2 = precioKilo;

            AddAdtlBusinessRules();
        }

        public PESAJES_BO(string codigo, DateTime fecha, TiposOperacion tOp, short peso,short ultimaGanancia)
        {
            _alreadyExists = true;
            this._CODIGO = codigo;
            this.FECHA = fecha;
            this.OPERACION = (short) tOp;
            this._Peso= peso;
            this._ultimaGanancia = ultimaGanancia;
        }


        public PESAJES_BO(Operacion_BO oBo)
        {
            this._CODIGO = oBo.CODIGO;
            this._FECHA = oBo.FECHA;
            this._OPERACION = oBo.OPERACION;
        }

        public PESAJES_BO() { }

        #endregion

        #region Methods
        private static TiposGananciaDiaria getTipoGanancia(short ganancia )
        {
            TiposGananciaDiaria tgd = TiposGananciaDiaria.Buena;

            if ((ganancia > 0) && (ganancia < 300))
            {
                tgd = TiposGananciaDiaria.Regular;
            }

            if ((ganancia < 0) && (ganancia > -1200))
            {
                tgd = TiposGananciaDiaria.Perdida;
            }

            if ((ganancia <= -1200) || (ganancia >= 1200))
            {
                tgd = TiposGananciaDiaria.Erronea;
            }

            return tgd;
        }

        public new void Guardar()
        {
            using (GlContext gContext = new GlContext())
            {
                currentPesajeDO = new PESAJE();
                currentPesajeDO.Codigo = this.CODIGO;
                currentPesajeDO.Fecha = this.FECHA;
                currentPesajeDO.Peso = this.Peso;
                currentPesajeDO.Operacion = (short)this.OPERACION;
                currentPesajeDO.lote = this.lote; //TODO: Review if this has same issue as subsonic bug
                gContext.PESAJES.Add(currentPesajeDO);
                gContext.SaveChanges();
            }
        }

        public void Delete()
        {
            using (GlContext gContext = new GlContext())
            {
                currentPesajeDO = gContext.PESAJES.FirstOrDefault(p => p.Codigo == this._CODIGO && p.Fecha == this._FECHA && p.Operacion == this._OPERACION);
                if (currentPesajeDO == null)
                {
                    throw new Exception("Codigo a borrar ({0}) no existe");
                }

                gContext.PESAJES.Remove(currentPesajeDO);
                gContext.SaveChanges();
            }
        }

        #endregion

        #region Validation Rules

        private static bool ValidaCodigo<T>(T target, Csla.Validation.RuleArgs e) where T : PESAJES_BO
        {
            string message = string.Empty;
            bool success = true;

            if (string.IsNullOrEmpty(target.CODIGO))
            {
                e.Description = "";
                success = false;
                return success;
            }

            if (utilities.CodigoEsValido(target.CODIGO, ref message, TiposOperacion.Pesaje_Carne) == false)
            {
                e.Description = message;
                success = false;
            }

            using (GlContext glContext = new GlContext())
            {
                if (glContext.PESAJES.Any(p => p.Codigo == target.CODIGO && p.Fecha == target.FECHA))
                {
                    e.Description = string.Format("Ya se ha registrado un pesaje para {0} en esta fecha", target.CODIGO);
                    success = false;
                }
            }
            return success;
        }

        private static bool ValidaPeso<T>(T target, Csla.Validation.RuleArgs e) where T : IOperacion
        {
            return utilities.ValidaPeso(target.Peso,e);
        }

        protected void AddAdtlBusinessRules()
        {
            try
            {
                ValidationRules.AddRule(new Csla.Validation.RuleHandler<PESAJES_BO,RuleArgs>(ValidaPeso), "Peso");
                ValidationRules.AddRule(new Csla.Validation.RuleHandler<PESAJES_BO, RuleArgs>(ValidaCodigo), "CODIGO");
            }
            catch (Exception ex)
            {
                throw (new Exception("AddBusinessRules: " + ex.Message, ex));
            }
        }

        #endregion

    }

    public class Pesajes : BindingListView<PESAJES_BO> 
    {
        public void Setfecha(DateTime fecha)
        {
            foreach (PESAJES_BO item in this)
            {
                item.FECHA = fecha.Date;
                item.IsValid();
            }
        }

    }

}
